package com.zone.api.di

import com.google.gson.GsonBuilder
import com.zone.api.http.BaseX509TrustManager
import com.zone.api.http.ConverterKey
import com.zone.api.http.HttpCookieJar
import com.zone.api.http.InterceptorKey
import com.zone.api.http.SSLSocketClient
import com.zone.api.http.SSLSocketClient.getSSLSocketFactory
import dagger.Module
import dagger.Provides
import dagger.multibindings.IntoMap
import okhttp3.CookieJar
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.security.SecureRandom
import java.util.concurrent.TimeUnit
import javax.inject.Named
import javax.inject.Provider
import javax.inject.Singleton
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

@Module
class RetrofitModule {

    companion object {
        const val NAME_BASE_URL = "baseUrl"
        const val NAME_DEBUG = "httpDebug"
    }

    @Provides
    @Singleton
    fun provideRetrofitProvider(
        converterFactories: MutableMap<Int, Provider<Converter.Factory>>,
        okHttpClient: OkHttpClient
    ): RetrofitProvider {
        return RetrofitProvider(converterFactories, okHttpClient)
    }

    @Provides
    @Singleton
    fun provideRetrofit(retrofitProvider: RetrofitProvider): Retrofit {
        return retrofitProvider.getRetrofit()
    }

    @Singleton
    @Provides
    fun provideOkHttpClient(
        loggingInterceptor: HttpLoggingInterceptor,
        interceptors: MutableMap<Int, Provider<Interceptor>>,
        cookieJar: CookieJar,
        x509TrustManager: X509TrustManager
    ): OkHttpClient {
        val okHttpBuild = OkHttpClient.Builder()
            .sslSocketFactory(getSSLSocketFactory(x509TrustManager), x509TrustManager)
            .addNetworkInterceptor(loggingInterceptor)//拦截器
            .cookieJar(cookieJar).hostnameVerifier { _, _ -> true }
            .protocols(listOf(Protocol.HTTP_1_1, Protocol.HTTP_2))
        interceptors.keys.sortedByDescending { it }.forEach {
            interceptors[it]?.get()?.let { inter ->
                okHttpBuild.addInterceptor(inter)
            }
        }

        okHttpBuild.callTimeout(5000, TimeUnit.SECONDS)
        okHttpBuild.connectTimeout(3000, TimeUnit.SECONDS)
        okHttpBuild.readTimeout(10000, TimeUnit.SECONDS)
        okHttpBuild.writeTimeout(10000, TimeUnit.SECONDS)

        return okHttpBuild.build()
    }


    @Singleton
    @Provides //证书验证
    fun provideX509TrustManager(): X509TrustManager {
        return BaseX509TrustManager()
    }

    @Singleton
    @Provides
    fun provideSSLSocketFactory(): SSLSocketFactory {
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, SSLSocketClient.getTrustManager(), SecureRandom())
        return sslContext.socketFactory
    }

    @Provides
    @IntoMap
    @InterceptorKey(0)//拦截器
    fun getInterceptor(): Interceptor {
        return ApiInterceptor()
    }

    @Singleton
    @Provides //日志拦截器
    fun getHttpLogInterceptor(@Named(NAME_DEBUG) isDebug: Boolean): HttpLoggingInterceptor {
        val interceptor = HttpLoggingInterceptor()
        val level = if (isDebug) HttpLoggingInterceptor.Level.BODY
        else HttpLoggingInterceptor.Level.NONE
        interceptor.level = level
        return interceptor
    }


    @Provides
    @IntoMap
    @ConverterKey(0)//内容转换器
    fun provideGsonConverterFactory(): Converter.Factory {
        return GsonConverterFactory.create(
            GsonBuilder().setPrettyPrinting().serializeNulls().create()
        )
    }

    @Singleton
    @Provides
    fun provideCookieJar(): CookieJar {
        return HttpCookieJar()
    }
}